package com.jackson.spring.aop.impl;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Repository;

/**
 * 存在多个切面时，@Order(2) 来决定优先级，数字越小，优先级越高，先执行
 * 把这个类声明成一个切面：需要把该类放入到IOC容器中、在声明为一个切面
 * @author jackson
 *
 */
@Order(2)
@Aspect
@Repository
public class LogingAspectj {

	
	/**
	 * 定义一个方法用于声明切入点表达式，此方法内不需要写内容
	 * 使用 @Pointcut 用与声明切入点表达式
	 */
	@Pointcut("execution(* com.jackson.spring.aop.impl.*.*(int, int)))")
	public void daspectjExpression(){}
	/**
	 * 在 com.jackson.spring.aop.ArithmeticCalculator 接口的每个方法开始之前执行这个方法。
	 */
	@Before("daspectjExpression()")
	public void beforeMethod(JoinPoint joinpoint){
		String methodname = joinpoint.getSignature().getName();
		System.out.println("the mothod begin" +methodname +" begin  with "+Arrays.asList(joinpoint.getArgs()));
	}
	
	/**
	 * 在方法执行后执行的通知，无论是否发生异常
	 * @param joinpoint
	 */
	@After("daspectjExpression()")
	public void afterMethod(JoinPoint joinpoint){
		String methodname = joinpoint.getSignature().getName();
		System.out.println("the mothod " +methodname +" end  with ");
	}
	
	/**
	 * 在方法正常结束后执行的方法
	 * 返回通知是可以访问到方法的返回值得
	 * @param joinpoint
	 * @param result
	 */
	@AfterReturning(value="daspectjExpression()",returning="result1")
	public void afterReturnMethod(JoinPoint joinpoint,Object result1){
		String methodname = joinpoint.getSignature().getName();
		System.out.println("the mothod " +methodname +" @AfterReturning  with result "+result1);
	}
	
	/**
	 * 在目标方法出现异常时，会执行的代码，而且访问到异常对象，且可以指定在出现特定异常时，在执行通知。
	 * @param joinpoint
	 * @param ex
	 */
	@AfterThrowing(value="daspectjExpression()",throwing="ex")
	public void afterThrowingMethod(JoinPoint joinpoint,Exception ex){
		String methodname = joinpoint.getSignature().getName();
		System.out.println("the mothod " +methodname +"  @AfterThrowing with   "+ex);
	}
	
	/**
	 * 环绕通知需要携带ProceedingJoinPoint 类型的参数
	 * 环绕通知类似于动态代理的全过程：ProceedingJoinPoint 类型的参数可以决定是否执行目标方法。
	 * 环绕通知必须要有个返回值，返回值即为目标方法的返回值。
	 * @param pjp
	 *//*
	@Around("execution(* com.jackson.spring.aop.impl.*.*(int, int)))")
	public Object aroundMethod(ProceedingJoinPoint pjp){
		 Object result = null;
		 String methodName =  pjp.getSignature().getName();
		 try {
			 // 前置通知
			 System.out.println(" aroundMethod the mothod " +methodName +" begin with "+Arrays.asList(pjp.getArgs()));
			 result = pjp.proceed();
			 //后置返回通知
			 System.out.println("the mothod " +methodName +" @AfterReturning  with result "+result);
		} catch (Throwable e) {
			e.printStackTrace();
			//异常通知
			System.out.println("the mothod " +methodName +"  @AfterThrowing with   "+e);
		}
		 //后置通知
		 System.out.println("the mothod " +methodName +" end  with ");
		return result;
	}*/
}
